{*******************************************************************************
* The contents of this file are used with permission, subject to the Mozilla   *
* Public License Version 1.1 (the "License"); you may not use this file except *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.mozilla.org/MPL/                                                  *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for *
* the specific language governing rights and limitations under the License.    *
*                                                                              *
* The Original Code is distributed as part of the "mediate" product and is     *
* Copyright (C) @home media limited. All Rights Reserved.                      *
*                                                                              *
* Email: support@athomemedia.co.uk                                             *
* Web:   http://www.athomemedia.co.uk                                          *
*******************************************************************************}

unit GridObjects;

interface

uses Classes, AHMTypes, Bitmaps;

type
  TAHMGridActions = class
  private
    FSelectFunction: String;
    FSelectTarget: String;
    FSelectParam: String;
    FFocusFunction: String;
    FFocusTarget: String;
    FFocusParam: String;
    FUnFocusFunction: String;
    FUnFocusTarget: String;
    FUnFocusParam: String;
  public
    property OnSelectFunction: String read FSelectFunction write FSelectFunction;
    property OnSelectTarget: String read FSelectTarget write FSelectTarget;
    property OnSelectParam: String read FSelectParam write FSelectParam;
    property OnFocusFunction: String read FFocusFunction write FFocusFunction;
    property OnFocusTarget: String read FFocusTarget write FFocusTarget;
    property OnFocusParam: String read FFocusParam write FFocusParam;
    property OnUnFocusFunction: String read FUnFocusFunction write FUnFocusFunction;
    property OnUnFocusTarget: String read FUnFocusTarget write FUnFocusTarget;
    property OnUnFocusParam: String read FUnFocusParam write FUnFocusParam;
    procedure ProcessSelect;
    procedure ProcessFocus;
    procedure ProcessUnFocus;
    procedure Assign(Source: TAHMGridActions);
  end;

  TAHMGridObject = class
  private
    FIndex: String;
    FWideIndex: WideString;
    FText: String;
    FDesc: String;
    FData: String;
    FValue: WideString;
    FImageURL: WideString;
    FImageIndex: String;
    FBitmap: TAHMBitmap;
    FChecked: Boolean;
    FSharedBitmap: Boolean;
    FState: TAHMControlState;
    FActions: TAHMGridActions;
  protected
    function GetPrefix: String;
  public
    destructor Destroy; override;
    property Index: String read FIndex write FIndex;
    property WideIndex: WideString read FWideIndex write FWideIndex;
    property Text: String read FText write FText;
    property Description: String read FDesc write FDesc;
    property Data: String read FData write FData;
    property Value: WideString read FValue write FValue;
    property Prefix: String read GetPrefix;
    property Checked: Boolean read FChecked write FChecked;
    property State: TAHMControlState read FState write FState;
    property ImageURL: WideString read FImageURL write FImageURL;
    property ImageIndex: String read FImageIndex write FImageIndex;
    property Bitmap: TAHMBitmap read FBitmap;
    property SharedBitmap: Boolean read FSharedBitmap;
    property Actions: TAHMGridActions read FActions;
    procedure ShareBitmap(Bitmap: TAHMBitmap);
    procedure UnshareBitmap;
    procedure LoadBitmapThumbnail(Width, Height: Single);
    procedure AddActions(OnSelectFunction, OnSelectTarget, OnSelectParam,
                         OnFocusFunction, OnFocusTarget, OnFocusParam,
                         OnUnFocusFunction, OnUnFocusTarget, OnUnFocusParam: String);
  end;

  TAHMGridObjectList = class
  private
    FObjects: TList;
  protected
    function GetCount: Integer;
    function GetObject(Index: Integer): TAHMGridObject;
  public
    constructor Create;
    destructor Destroy; override;
    property Count: Integer read GetCount;
    property Objects[Index: Integer]: TAHMGridObject read GetObject;
    procedure Clear;
    function AddObject: TAHMGridObject;
    function LookupObjectIndex(Index: String): Integer; overload;
    function LookupObjectIndex(Index: WideString): Integer; overload;
  end;

implementation

uses ApplicationManager;

// TAHMGridActions

procedure TAHMGridActions.ProcessSelect;
begin
  // Process selection actions
  with ApplicationManagerInstance.ActionManager do
    EnqueueAction(FSelectFunction, FSelectTarget, FSelectParam);
end;

procedure TAHMGridActions.ProcessFocus;
begin
  // Process selection actions
  with ApplicationManagerInstance.ActionManager do
    EnqueueAction(FFocusFunction, FFocusTarget, FFocusParam);
end;

procedure TAHMGridActions.ProcessUnFocus;
begin
  // Process selection actions
  with ApplicationManagerInstance.ActionManager do
    EnqueueAction(FUnFocusFunction, FUnFocusTarget, FUnFocusParam);
end;

procedure TAHMGridActions.Assign(Source: TAHMGridActions);
begin
  FSelectFunction  := Source.OnSelectFunction;
  FSelectTarget    := Source.OnSelectTarget;
  FSelectParam     := Source.OnSelectParam;
  FFocusFunction   := Source.OnFocusFunction;
  FFocusTarget     := Source.OnFocusTarget;
  FFocusParam      := Source.OnFocusParam;
  FUnFocusFunction := Source.OnUnFocusFunction;
  FUnFocusTarget   := Source.OnUnFocusTarget;
  FUnFocusParam    := Source.OnUnFocusParam;
end;

// TAHMGridObject

destructor TAHMGridObject.Destroy;
begin
  if not FSharedBitmap then FBitmap.Free;
  FActions.Free;

  inherited Destroy;
end;

//TODO: refactor this into a utility function somewhere (GetPrefix)
function TAHMGridObject.GetPrefix: String;
const
  NUMERICS = ['0'..'9'];
  ALPHAS = ['a'..'z', 'A'..'Z'];
  MAX_NUM = 3; // Maximum numeric prefix length
var
  i: Integer;
begin
  // Set default result - empty prefix
  Result := '';

  // First pass - remove anything but alpha and numerics
  for i := 1 to Length(FText) do
    if (FText[i] in ALPHAS) or (FText[i] in NUMERICS) then
      Result := Result + FText[i];

  // Second pass - generate prefix (max 3 numerics or 1 alpha)
  for i := 1 to Length(Result) do
    if (i > MAX_NUM) or not (Result[i] in NUMERICS) then
    begin
      if i > 1 then Result := Copy(Result, 1, i - 1)
               else Result := Copy(Result, 1, 1);
      Break;
    end;
end;

procedure TAHMGridObject.ShareBitmap(Bitmap: TAHMBitmap);
begin
  // Free private instance and use shared bitmap
  if not FSharedBitmap then FBitmap.Free;
  FBitmap := Bitmap;
  FSharedBitmap := True;
end;

procedure TAHMGridObject.UnshareBitmap;
begin
  // Create a private bitmap instance if required
  if FSharedBitmap or (FBitmap = nil) then FBitmap := TAHMBitmap.Create(FIndex);
  FSharedBitmap := False;
end;

procedure TAHMGridObject.LoadBitmapThumbnail(Width, Height: Single);
var
  Thumbnail: TAHMBitmap;
begin
  if FSharedBitmap or (FBitmap = nil) then
  begin
    // Submit thumbnail request - may be generated asynchronously
    with ApplicationManagerInstance.ThumbnailGenerator do
      Thumbnail := MakeImageThumb(FImageURL, Width, Height);

    if Assigned(Thumbnail) then
    begin
      FBitmap := Thumbnail;
      FSharedBitmap := False;
    end;
  end;
end;

procedure TAHMGridObject.AddActions(OnSelectFunction, OnSelectTarget, OnSelectParam,
                                    OnFocusFunction, OnFocusTarget, OnFocusParam,
                                    OnUnFocusFunction, OnUnFocusTarget, OnUnFocusParam: String);
begin
  // Create grid actions instance if required
  if FActions = nil then FActions := TAHMGridActions.Create;

  FActions.OnSelectFunction := OnSelectFunction;
  FActions.OnSelectTarget := OnSelectTarget;
  FActions.OnSelectParam := OnSelectParam;
  FActions.OnFocusFunction := OnFocusFunction;
  FActions.OnFocusTarget := OnFocusTarget;
  FActions.OnFocusParam := OnFocusParam;
  FActions.OnUnFocusFunction := OnUnFocusFunction;
  FActions.OnUnFocusTarget := OnUnFocusTarget;
  FActions.OnUnFocusParam := OnUnFocusParam;
end;

// TAHMGridObjectList

constructor TAHMGridObjectList.Create;
begin
  inherited Create;

  FObjects := TList.Create;
end;

destructor TAHMGridObjectList.Destroy;
var
  i: Integer;
begin
  for i := 0 to Pred(FObjects.Count) do
    TAHMGridObject(FObjects.Items[i]).Free;
  FObjects.Free;

  inherited Destroy;
end;

function TAHMGridObjectList.GetCount: Integer;
begin
  Result := FObjects.Count;
end;

function TAHMGridObjectList.GetObject(Index: Integer): TAHMGridObject;
begin
  if (Index >= 0) and (Index < FObjects.Count) then
    Result := TAHMGridObject(FObjects.Items[Index])
  else
    Result := nil;
end;

procedure TAHMGridObjectList.Clear;
var
  i: Integer;
begin
  for i := 0 to Pred(FObjects.Count) do
    TAHMGridObject(FObjects.Items[i]).Free;
  FObjects.Clear;
end;

function TAHMGridObjectList.AddObject: TAHMGridObject;
begin
  Result := TAHMGridObject.Create;
  FObjects.Add(Result);
end;

function TAHMGridObjectList.LookupObjectIndex(Index: String): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Pred(FObjects.Count) do
    if TAHMGridObject(FObjects.Items[i]).Index = Index then
    begin
      Result := i;
      Break;
    end;
end;

function TAHMGridObjectList.LookupObjectIndex(Index: WideString): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to Pred(FObjects.Count) do
    if TAHMGridObject(FObjects.Items[i]).WideIndex = Index then
    begin
      Result := i;
      Break;
    end;
end;


end.
